Overall Objective

Deterine the concentration of total exosomes in differnt thryroid diseased states, Normal, TgAA+, and Hypothyroid. This experiment was controlled for breed and age, while sex was not. From each of the diseased states two good quality serum samples were choosen and exosomes were isolated using the total exosome isolation reagent (ThermoFisher) and resuspended in 30ul of PBS. Samples were then blinded (randomly assigned numbers) and analzed by Nanosight (NS300 Malvern) nanoparticle tracking analysis. Analysis of all six trial samples were completed in one day with before and after controls of 100nm polystyrene beads (1:125 in PBS) to determine intra and inter assay variability.

Nanosight measurement/ experimental setup

Samples and standards were measured twice by two separate injections (from separate tubes) into the machine. Three, thirty second 30 second videos were recorded and analyzed by Nanosight NTA 3.2 and exported raw data was exported as a .csv file which was minimally processed for easy import into R.

Nanosight acquisition settings

Gain Level Threshold
Standards 1 11 4
Samples 1 12 4

Load Libraries

library(tidyverse)
library(cowplot)
library(broom)
library(pwr)
library(plotly)

Import data

There are total of three datasets that will be used for this experiment. The raw data from all the samples, the 100nm standards to determine the inter and intra-assay variation as well as the timecourse data that serves as the ‘key’ to identify Sample_ID to the experiment condition.

setwd("~/GitHub/Experiments/Thyroiditis/data/")
#setwd("~/Library/Mobile\ Documents/com~apple~CloudDocs/time-course/data")
rawdata <- "samples_-ExperimentSummary.csv"
key <- "key.csv"
standards <- "std_combined-ExperimentSummary.csv"
data <- read_csv(rawdata)
key <- read_csv(key)
std <- read_csv(standards)

Convert data from ‘wide’ to ‘long’ format

The data is in the classical ‘wide’ format which is easy to understand from a human cognition perspective but we need to make it ‘long’ so it’s easier to process in R.

data1 <- data %>%
  gather(Sample,Count,2:37)
# Separate samples by identifiers 
data2 <- data1 %>% 
  separate(Sample, into=c("Sample_ID","Dilution_factor","Injection","Tech_rep", sep = "_")) %>% 
  select(-`_`)
std1 <- std %>% 
  gather(Sample,Count,2:13)
std2 <- std1 %>% 
  separate(Sample, into=c("Sample_ID","When","Dilution_factor","Nano_day","Injection","Tech_Rep", sep = "_")) %>% 
  select(-`_`)
std2$Sample_ID <- as.factor(std2$Sample_ID)
std2$When <- as.factor(std2$When)
std2$Dilution_factor <- as.numeric(std2$Dilution_factor)
std2$Injection<- as.factor(std2$Injection)
std2$Nano_day <- as.numeric(std2$Nano_day)

Backcalculate standards

Obtain the ‘True_count’ by multiplying the ‘Count’ column by the ‘Dilution factor’

std2 <- std2 %>% 
  mutate(True_Count=Dilution_factor*Count)
std2$Nano_day <-  factor(std2$Nano_day, levels=c('1'))
std2$When <- factor(std2$When, levels=c('before','after'))

Summarize three technical replicates

std3 <- std2 %>% 
  group_by(particle_size,Sample_ID,When,Dilution_factor,Nano_day,Injection) %>% 
  summarise( tech_N = length(True_Count),
             tech_mean = mean(True_Count),
             tech_sd = sd(True_Count),
             tech_se = tech_sd/sqrt(tech_N))
std3

Summarize by injection

std4 <- std3 %>% 
  group_by(Nano_day,When,particle_size) %>% 
  summarise( inj_N = length(tech_mean),
             inj_mean = mean(tech_mean),
             inj_sd = sd(tech_mean),
             inj_se = inj_sd/sqrt(inj_N))
std4

Plot before and after plots, facet by experimental day

std_day <- std4 %>% 
  ggplot(aes(x=particle_size,y=inj_mean,color=When))+
  geom_ribbon(aes(ymin=inj_mean-inj_se, ymax=inj_mean+inj_se),alpha=0.2,fill = alpha('grey12', 0.2)) + #error bars
  geom_line(size=2) + xlim(0,500)+ #line size, x-axis scale
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Particle Size") + # X axis label
  ylab("\nMean Particle Concentration\n(Particles/ml)\n") + # Y axis label
  ggtitle("Nanosight Histogram of\n100nm standards")+ #title
  labs(color="When")+ #Label table title
  facet_grid(. ~ Nano_day)
std_day

Plot facet by when and experimental day

ggsave(std_day_facet, "Standards_histogram.png", 
       height = 5, width = 7, dpi = 300, units= "in")
Error: `device` must be NULL, a string or a function.

Particle concentrations from each experimental day

std_df <- std4 %>% 
  group_by(Nano_day,When) %>% 
  summarise(total=sum(inj_mean))
std_df

Bar graph of particle concentrations

std_bar_plot <- std_df %>% 
  ggplot(aes(x=Nano_day,y=total,fill=When))+
  geom_col(position="dodge")+
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Experimental Day") + # X axis label
  ylab("\nMean Concentration\n(Particles/ml)\n") + # Y axis label
  ggtitle("Nanosight Histogram of\n100nm standards")+ #title
  labs(color="When") #Label table title
std_bar_plot

# ggsave(plot = std_bar_plot, "std_bar_plot.png",
#        height = 5, width = 7, dpi = 300, units= "in")

Intraassay variability

Intra.assay_cv <- std_df %>% 
  group_by(Nano_day) %>% 
  summarise(Day_N = length(total),
             Day_mean = mean(total),
             Day_sd = sd(total),
             Day_se = Day_sd/sqrt(Day_N),
            Day_cv = Day_sd/Day_mean )
Intra.assay_cv
write_csv(Intra.assay_cv, "Intra.assay_cv.csv")

Inter assay variability

Inter.assay <- Intra.assay_cv %>% 
 summarise(Exp_N = length(Day_mean),
             Exp_mean = mean(Day_mean),
             Exp_sd = sd(Day_mean),
             Exp_se = Exp_sd/sqrt(Exp_N),
            Exp_cv = Exp_sd/Exp_mean )
Inter.assay
# write_csv(Inter.assay, "Inter.assay.csv")

Factor the data into categorical variables

# Refactoring Columns for samples
data2$Sample_ID <- as.factor(data2$Sample_ID)
data2$Dilution_factor <- as.numeric(data2$Dilution_factor)
data2$Injection<- as.factor(data2$Injection)
data2$Tech_rep <- as.numeric(data2$Tech_rep)
# Refactoring COlumns for timecourse
key$Sample_ID <- as.factor(key$Sample_ID)
key$Profile <- as.factor(key$Profile)
key$Sex <- as.factor(key$Sex)
key$Age <- as.numeric(key$Age)

Back calculate the original concentration of the sample

data2 <- data2 %>% 
  mutate(True_Count=Dilution_factor*Count)
data2

Average the three technical replicate readings

data3 <- data2 %>% 
  group_by(particle_size,Sample_ID,Dilution_factor,Injection) %>% 
  summarise( tech_N = length(True_Count),
             tech_mean = mean(True_Count),
             tech_sd = sd(True_Count),
             tech_se = tech_sd/sqrt(tech_N))
data3
test1 <- left_join(key,data3, by= "Sample_ID")

Summarize samples by injection (average both injections)

data4 <- data3 %>% 
  group_by(particle_size,Sample_ID,Dilution_factor) %>% 
  summarise( inj_N = length(tech_mean),
             inj_mean = mean(tech_mean),
             inj_sd = sd(tech_mean),
             inj_se = inj_sd/sqrt(inj_N))
data4
test2 <- left_join(key,data4, by= "Sample_ID")
test2

Quick visualizations

Graphing all samples

test1$Sample_ID_correct = factor(test1$Sample_ID, levels=c('1','2','3','4','5','6'))
test1$Profile = factor(test1$Profile, levels=c("Normal", "TgAA", "Hypothyroid"))
graph1 <- test1 %>%
  ggplot(aes(x=particle_size, y=tech_mean,color=Injection ))+ #plot
  geom_ribbon(aes(ymin=tech_mean-tech_se,
                  ymax=tech_mean+tech_se),
                  alpha=0.2,fill = alpha('grey12', 0.2)) + #error bars
  geom_line(size=2.0) + xlim(0,500)+ #line size, x-axis scale
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Particle Size") + # X axis label
  ylab("\nMean Particle Concentration\n(Particles/ml)\n") + # Y axis label
  ggtitle("Nanosight Histogram of\nMouse Plasma Throughout Pregnancy")+ #title
  labs(color="Injection")+ #Label table title
  facet_wrap( ~ Sample_ID_correct, ncol=6)
graph1

Looking at individual gestational day nanosight line plots

Sample 1

sample1_histogram <- test1 %>%
  filter(Sample_ID == '1') %>% 
  ggplot(aes(x=particle_size, y=tech_mean,color=Injection ))+ #plot
  geom_ribbon(aes(ymin=tech_mean-tech_se,
                  ymax=tech_mean+tech_se),
                  alpha=0.2,fill = alpha('grey12', 0.2)) + #error bars
  geom_line(size=1.0) + xlim(0,500)+ #line size, x-axis scale
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Particle Size") + # X axis label
  ylab("\nMean Particle Concentration\n(Particles/ml)\n") + # Y axis label
  ggtitle("Nanosight Histogram of\n TgAA+ Male")+ #title
  labs(color="Injection")+ #Label table title
  facet_wrap( ~ Sample_ID_correct)+
  geom_vline(xintercept = 140)+
  annotate("text", x= 235, y = 3E9, label= "140nm")
sample1_histogram

# ggsave(plot = virgin_histogram, "virgin_histogram.png",
#        height = 10, width = 14, dpi = 300, units= "in")

Sample 2

sample1_histogram <- test1 %>%
  filter(Sample_ID == '2') %>% 
  ggplot(aes(x=particle_size, y=tech_mean,color=Injection ))+ #plot
  geom_ribbon(aes(ymin=tech_mean-tech_se,
                  ymax=tech_mean+tech_se),
                  alpha=0.2,fill = alpha('grey12', 0.2)) + #error bars
  geom_line(size=1.0) + xlim(0,500)+ #line size, x-axis scale
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Particle Size") + # X axis label
  ylab("\nMean Particle Concentration\n(Particles/ml)\n") + # Y axis label
  ggtitle("Nanosight Histogram of\nNormal Female Serum")+ #title
  labs(color="Injection")+ #Label table title
  facet_wrap( ~ Sample_ID_correct)+
  geom_vline(xintercept = 140)+
  annotate("text", x= 235, y = 3E9, label= "140nm")
sample1_histogram

# ggsave(plot = gd5.5_histogram, "gd5.5_histogram.png",
#        height = 10, width = 14, dpi = 300, units= "in")

Sample 3

sample3_histogram <- test1 %>%
  filter(Sample_ID == '3') %>% 
  ggplot(aes(x=particle_size, y=tech_mean,color=Injection ))+ #plot
  geom_ribbon(aes(ymin=tech_mean-tech_se,
                  ymax=tech_mean+tech_se),
                  alpha=0.2,fill = alpha('grey12', 0.2)) + #error bars
  geom_line(size=1.0) + xlim(0,500)+ #line size, x-axis scale
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Particle Size") + # X axis label
  ylab("\nMean Particle Concentration\n(Particles/ml)\n") + # Y axis label
  ggtitle("Nanosight Histogram of\nHypothyroid Male Serum")+ #title
  labs(color="Injection")+ #Label table title
  facet_wrap( ~ Sample_ID_correct)+
  geom_vline(xintercept = 140)+
  annotate("text", x= 235, y = 4E9, label= "140nm")
sample3_histogram

# ggsave(plot = gd10.5_histogram, "gd10.5_histogram.png",
#        height = 10, width = 14, dpi = 300, units= "in")

Sample 4

sample4_histogram <- test1 %>%
  filter(Sample_ID == '4') %>% 
  ggplot(aes(x=particle_size, y=tech_mean,color=Injection ))+ #plot
  geom_ribbon(aes(ymin=tech_mean-tech_se,
                  ymax=tech_mean+tech_se),
                  alpha=0.2,fill = alpha('grey12', 0.2)) + #error bars
  geom_line(size=1.0) + xlim(0,500)+ #line size, x-axis scale
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Particle Size") + # X axis label
  ylab("\nMean Particle Concentration\n(Particles/ml)\n") + # Y axis label
  ggtitle("Nanosight Histogram of\nTgAA+ Female Serum")+ #title
  labs(color="Injection")+ #Label table title
  facet_wrap( ~ Sample_ID_correct)+
  geom_vline(xintercept = 140)+
  annotate("text", x= 235, y = 3E9, label= "140nm")
sample4_histogram

# ggsave(plot = gd14.5_histogram, "gd14.5_histogram.png",
#        height = 10, width = 14, dpi = 300, units= "in")

Sample 5

sample5_histogram <- test1 %>%
  filter(Sample_ID == '5') %>% 
  ggplot(aes(x=particle_size, y=tech_mean,color=Injection ))+ #plot
  geom_ribbon(aes(ymin=tech_mean-tech_se,
                  ymax=tech_mean+tech_se),
                  alpha=0.2,fill = alpha('grey12', 0.2)) + #error bars
  geom_line(size=1.0) + xlim(0,500)+ #line size, x-axis scale
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Particle Size") + # X axis label
  ylab("\nMean Particle Concentration\n(Particles/ml)\n") + # Y axis label
  ggtitle("Nanosight Histogram of\nNormal Male Serum")+ #title
  labs(color="Injection")+ #Label table title
  facet_wrap( ~ Sample_ID_correct)+
  geom_vline(xintercept = 140)+
  annotate("text", x= 235, y = 3E9, label= "140nm")
sample5_histogram

# ggsave(plot = gd17.5_histogram, "gd17.5_histogram.png",
#        height = 10, width = 14, dpi = 300, units= "in")

Sample 6

sample6_histogram <- test1 %>%
  filter(Sample_ID == '6') %>% 
  ggplot(aes(x=particle_size, y=tech_mean,color=Injection ))+ #plot
  geom_ribbon(aes(ymin=tech_mean-tech_se,
                  ymax=tech_mean+tech_se),
                  alpha=0.2,fill = alpha('grey12', 0.2)) + #error bars
  geom_line(size=1.0) + xlim(0,500)+ #line size, x-axis scale
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Particle Size") + # X axis label
  ylab("\nMean Particle Concentration\n(Particles/ml)\n") + # Y axis label
  ggtitle("Nanosight Histogram of\nHypothyroid Male Serum")+ #title
  labs(color="Injection")+ #Label table title
  facet_wrap( ~ Sample_ID_correct)+
  geom_vline(xintercept = 140)+
  annotate("text", x= 235, y = 4E10, label= "140nm")
sample6_histogram

# ggsave(plot = one.day.post.partum_histogram, "one.day.post.partum_histogram.png",
#        height = 10, width = 14, dpi = 300, units= "in")

Particle concentration values for each of the 36 samples

test3 <- test2 %>% 
  group_by(Profile,Sample_ID) %>% 
  summarise(particle_conc=sum(inj_mean))
test3
write_csv(test3, "Sample_means.csv")

Boxplot of all values

test3$Profile <- factor(test3$Profile, levels = c("Normal","TgAA", "Hypothyroid"))
plot1 <- test3 %>% 
  group_by(Profile) %>% 
  ggplot(aes(x= Profile, y = particle_conc/1E9, color=Profile)) +
  geom_boxplot(colour="black",fill=NA) + 
  geom_point(aes(text = paste("Sample ID:", Sample_ID)),
             position='jitter',size=3)+
  xlab("\nDisease State\n") + # X axis label
  ylab("\n10^9 Exosomes/ml\n") + # Y axis label
  ggtitle("Serum Exosome Concentration\nof Canine Disease States (All Samples)\n")+ #title
  labs(color="Profile")+ # Label table title
  scale_x_discrete( # Change X axis label
                  labels=c("Normal","TgAA+", "Hypothyroid")) +
  scale_color_discrete(labels=c("Normal","TgAA+", "Hypothyroid")) # Change Legend
plot1
ggsave(plot = plot1, "Exosome_boxplot_plot_all.png", height = 5, width = 7, units = "in", dpi = 600)

Plotly of all values

  ggplotly(plot1)

Box plot without sample 6

plot1_no_sample_6 <- test3 %>% 
  filter(!Sample_ID == '6') %>% 
  group_by(Profile) %>% 
  ggplot(aes(x= Profile, y = particle_conc/1E9, color=Profile)) +
  geom_boxplot(colour="black",fill=NA) + 
  geom_point(aes(text = paste("Sample ID:", Sample_ID)),
             position='jitter',size=3)+
  xlab("\nDisease State\n") + # X axis label
  ylab("\n10^9 Exosomes/ml\n") + # Y axis label
  ggtitle("Serum Exosome Concentration\nof Canine Disease States (Without sample 6)\n")+ #title
  labs(color="Profile")+ # Label table title
  scale_x_discrete( # Change X axis label
                  labels=c("Normal","TgAA+", "Hypothyroid")) +
  scale_color_discrete(labels=c("Normal","TgAA+", "Hypothyroid")) # Change Legend
plot1_no_sample_6
ggsave(plot = plot1_no_sample_6, "Exosome_boxplot_plot_no6.png", height = 5, width = 7, units = "in", dpi = 600)

Plotly without sample 6

  ggplotly(plot1_no_sample_6)
We recommend that you use the dev version of ggplot2 with `ggplotly()`
Install it with: `devtools::install_github('hadley/ggplot2')`

Summary statistics of particle concentration (averaging for each time point)

test4 <- test3 %>% 
  group_by(Profile) %>% 
  summarise(Profile_N=length(particle_conc),
            Profile_mean = mean(particle_conc),
            Profile_sd = sd(particle_conc),
            Profile_se = Profile_sd/sqrt(Profile_N))
test4
write_csv(test4,"Summary_statistics_for_each_profile.csv")

Bar plot

plot <- test4 %>% 
  ggplot(aes(x = Profile, y = Profile_mean/1E9, fill = Profile))+ #plot
  geom_col()+
  geom_errorbar(aes(ymin = Profile_mean/1e9-Profile_se/1e9,
                    ymax = Profile_mean/1e9+Profile_se/1e9), width=.4,
                size = 0.8, colour = "black", position = position_dodge(.9)) + #error bars
  xlab("\nDisease State\n") + # X axis label
  ylab("\nMean Concentration\n(10^9 Vesicles/ml)\n") + # Y axis label
  ggtitle("Serum Exosome Concentration\nof Canine Disease States(All Samples)\n")+ #title
  guides(fill=FALSE) + # Remove legend
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  scale_x_discrete( # Change X axis label
                  labels=c("Normal","TgAA+", "Hypothyroid")) +
  scale_color_discrete(labels=c("Normal","TgAA+", "Hypothyroid")) # Change Legend
plot
ggsave("Vesicle_barplot.png", height = 5, width = 7, units = "in", dpi = 600)

Statistics on ALL sizes

Shapiro test

tidy(shapiro.test(test3$particle_conc))
LS0tDQp0aXRsZTogIlRoeXJvaWRpdGlzIEV4b3NvbWUgQW5hbHlzaXMiDQphdXRob3I6ICJTZWFuIE5ndXllbiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICB0aGVtZTogZmxhdGx5DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCiNPdmVyYWxsIE9iamVjdGl2ZSANCg0KRGV0ZXJpbmUgdGhlIGNvbmNlbnRyYXRpb24gb2YgdG90YWwgZXhvc29tZXMgaW4gZGlmZmVybnQgdGhyeXJvaWQgZGlzZWFzZWQgc3RhdGVzLCBOb3JtYWwsIFRnQUErLCBhbmQgSHlwb3RoeXJvaWQuIFRoaXMgZXhwZXJpbWVudCB3YXMgY29udHJvbGxlZCBmb3IgYnJlZWQgYW5kIGFnZSwgd2hpbGUgc2V4IHdhcyBub3QuIEZyb20gZWFjaCBvZiB0aGUgZGlzZWFzZWQgc3RhdGVzIHR3byBnb29kIHF1YWxpdHkgc2VydW0gc2FtcGxlcyB3ZXJlIGNob29zZW4gYW5kIGV4b3NvbWVzIHdlcmUgaXNvbGF0ZWQgdXNpbmcgdGhlICB0b3RhbCBleG9zb21lIGlzb2xhdGlvbiByZWFnZW50IChUaGVybW9GaXNoZXIpIGFuZCByZXN1c3BlbmRlZCBpbiAzMHVsIG9mIFBCUy4gU2FtcGxlcyB3ZXJlIHRoZW4gYmxpbmRlZCAocmFuZG9tbHkgYXNzaWduZWQgbnVtYmVycykgYW5kIGFuYWx6ZWQgYnkgTmFub3NpZ2h0IChOUzMwMCBNYWx2ZXJuKSBuYW5vcGFydGljbGUgdHJhY2tpbmcgYW5hbHlzaXMuIEFuYWx5c2lzIG9mIGFsbCBzaXggdHJpYWwgc2FtcGxlcyB3ZXJlIGNvbXBsZXRlZCBpbiBvbmUgZGF5IHdpdGggYmVmb3JlIGFuZCBhZnRlciBjb250cm9scyBvZiAxMDBubSBwb2x5c3R5cmVuZSBiZWFkcyAoMToxMjUgaW4gUEJTKSB0byBkZXRlcm1pbmUgaW50cmEgYW5kIGludGVyIGFzc2F5IHZhcmlhYmlsaXR5Lg0KDQoNCiMjI05hbm9zaWdodCBtZWFzdXJlbWVudC8gZXhwZXJpbWVudGFsIHNldHVwDQpTYW1wbGVzIGFuZCBzdGFuZGFyZHMgd2VyZSBtZWFzdXJlZCB0d2ljZSBieSB0d28gc2VwYXJhdGUgaW5qZWN0aW9ucyAoZnJvbSBzZXBhcmF0ZSB0dWJlcykgaW50byB0aGUgbWFjaGluZS4gIFRocmVlLCB0aGlydHkgc2Vjb25kIDMwIHNlY29uZCB2aWRlb3Mgd2VyZSByZWNvcmRlZCBhbmQgYW5hbHl6ZWQgYnkgTmFub3NpZ2h0IE5UQSAzLjIgYW5kIGV4cG9ydGVkIHJhdyBkYXRhIHdhcyBleHBvcnRlZCBhcyBhIC5jc3YgZmlsZSB3aGljaCB3YXMgbWluaW1hbGx5IHByb2Nlc3NlZCBmb3IgZWFzeSBpbXBvcnQgaW50byBSLg0KDQoNCiMjI05hbm9zaWdodCBhY3F1aXNpdGlvbiBzZXR0aW5ncyAgDQp8fEdhaW58TGV2ZWx8VGhyZXNob2xkfCAgDQp8LS0tfC0tLXwtLS18LS0tfA0KfFN0YW5kYXJkc3wxfDExfDR8DQp8U2FtcGxlc3wxfDEyfDR8DQoNCiMjTG9hZCBMaWJyYXJpZXMNCg0KYGBge3IsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShjb3dwbG90KQ0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkocHdyKQ0KbGlicmFyeShwbG90bHkpDQpgYGANCg0KIyNJbXBvcnQgZGF0YQ0KDQpUaGVyZSBhcmUgdG90YWwgb2YgdGhyZWUgZGF0YXNldHMgdGhhdCB3aWxsIGJlIHVzZWQgZm9yIHRoaXMgZXhwZXJpbWVudC4gIFRoZSByYXcgZGF0YSBmcm9tIGFsbCB0aGUgc2FtcGxlcywgdGhlIDEwMG5tIHN0YW5kYXJkcyB0byBkZXRlcm1pbmUgdGhlIGludGVyIGFuZCBpbnRyYS1hc3NheSB2YXJpYXRpb24gYXMgd2VsbCBhcyB0aGUgdGltZWNvdXJzZSBkYXRhIHRoYXQgc2VydmVzIGFzIHRoZSAna2V5JyB0byBpZGVudGlmeSBTYW1wbGVfSUQgdG8gdGhlIGV4cGVyaW1lbnQgY29uZGl0aW9uLiAgDQpgYGB7ciwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Kc2V0d2QoIn4vR2l0SHViL0V4cGVyaW1lbnRzL1RoeXJvaWRpdGlzL2RhdGEvIikNCiNzZXR3ZCgifi9MaWJyYXJ5L01vYmlsZVwgRG9jdW1lbnRzL2NvbX5hcHBsZX5DbG91ZERvY3MvdGltZS1jb3Vyc2UvZGF0YSIpDQoNCnJhd2RhdGEgPC0gInNhbXBsZXNfLUV4cGVyaW1lbnRTdW1tYXJ5LmNzdiINCmtleSA8LSAia2V5LmNzdiINCnN0YW5kYXJkcyA8LSAic3RkX2NvbWJpbmVkLUV4cGVyaW1lbnRTdW1tYXJ5LmNzdiINCg0KDQpkYXRhIDwtIHJlYWRfY3N2KHJhd2RhdGEpDQprZXkgPC0gcmVhZF9jc3Yoa2V5KQ0Kc3RkIDwtIHJlYWRfY3N2KHN0YW5kYXJkcykNCmBgYA0KDQoNCiMjQ29udmVydCBkYXRhIGZyb20gJ3dpZGUnIHRvICdsb25nJyBmb3JtYXQNClRoZSBkYXRhIGlzIGluIHRoZSBjbGFzc2ljYWwgJ3dpZGUnIGZvcm1hdCB3aGljaCBpcyBlYXN5IHRvIHVuZGVyc3RhbmQgZnJvbSBhIGh1bWFuIGNvZ25pdGlvbiBwZXJzcGVjdGl2ZSBidXQgd2UgbmVlZCB0byBtYWtlIGl0ICdsb25nJyBzbyBpdCdzIGVhc2llciB0byBwcm9jZXNzIGluIFIuDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmRhdGExIDwtIGRhdGEgJT4lDQogIGdhdGhlcihTYW1wbGUsQ291bnQsMjozNykNCg0KIyBTZXBhcmF0ZSBzYW1wbGVzIGJ5IGlkZW50aWZpZXJzIA0KZGF0YTIgPC0gZGF0YTEgJT4lIA0KICBzZXBhcmF0ZShTYW1wbGUsIGludG89YygiU2FtcGxlX0lEIiwiRGlsdXRpb25fZmFjdG9yIiwiSW5qZWN0aW9uIiwiVGVjaF9yZXAiLCBzZXAgPSAiXyIpKSAlPiUgDQogIHNlbGVjdCgtYF9gKQ0KDQoNCnN0ZDEgPC0gc3RkICU+JSANCiAgZ2F0aGVyKFNhbXBsZSxDb3VudCwyOjEzKQ0KDQpzdGQyIDwtIHN0ZDEgJT4lIA0KICBzZXBhcmF0ZShTYW1wbGUsIGludG89YygiU2FtcGxlX0lEIiwiV2hlbiIsIkRpbHV0aW9uX2ZhY3RvciIsIk5hbm9fZGF5IiwiSW5qZWN0aW9uIiwiVGVjaF9SZXAiLCBzZXAgPSAiXyIpKSAlPiUgDQogIHNlbGVjdCgtYF9gKQ0KDQoNCnN0ZDIkU2FtcGxlX0lEIDwtIGFzLmZhY3RvcihzdGQyJFNhbXBsZV9JRCkNCnN0ZDIkV2hlbiA8LSBhcy5mYWN0b3Ioc3RkMiRXaGVuKQ0Kc3RkMiREaWx1dGlvbl9mYWN0b3IgPC0gYXMubnVtZXJpYyhzdGQyJERpbHV0aW9uX2ZhY3RvcikNCnN0ZDIkSW5qZWN0aW9uPC0gYXMuZmFjdG9yKHN0ZDIkSW5qZWN0aW9uKQ0Kc3RkMiROYW5vX2RheSA8LSBhcy5udW1lcmljKHN0ZDIkTmFub19kYXkpDQoNCmBgYA0KIyMjQmFja2NhbGN1bGF0ZSBzdGFuZGFyZHMNCk9idGFpbiB0aGUgJ1RydWVfY291bnQnIGJ5IG11bHRpcGx5aW5nIHRoZSAnQ291bnQnIGNvbHVtbiBieSB0aGUgJ0RpbHV0aW9uIGZhY3RvcicNCmBgYHtyfQ0Kc3RkMiA8LSBzdGQyICU+JSANCiAgbXV0YXRlKFRydWVfQ291bnQ9RGlsdXRpb25fZmFjdG9yKkNvdW50KQ0KDQpzdGQyJE5hbm9fZGF5IDwtICBmYWN0b3Ioc3RkMiROYW5vX2RheSwgbGV2ZWxzPWMoJzEnKSkNCnN0ZDIkV2hlbiA8LSBmYWN0b3Ioc3RkMiRXaGVuLCBsZXZlbHM9YygnYmVmb3JlJywnYWZ0ZXInKSkNCmBgYA0KDQojIyNTdW1tYXJpemUgdGhyZWUgdGVjaG5pY2FsIHJlcGxpY2F0ZXMNCmBgYHtyfQ0Kc3RkMyA8LSBzdGQyICU+JSANCiAgZ3JvdXBfYnkocGFydGljbGVfc2l6ZSxTYW1wbGVfSUQsV2hlbixEaWx1dGlvbl9mYWN0b3IsTmFub19kYXksSW5qZWN0aW9uKSAlPiUgDQogIHN1bW1hcmlzZSggdGVjaF9OID0gbGVuZ3RoKFRydWVfQ291bnQpLA0KICAgICAgICAgICAgIHRlY2hfbWVhbiA9IG1lYW4oVHJ1ZV9Db3VudCksDQogICAgICAgICAgICAgdGVjaF9zZCA9IHNkKFRydWVfQ291bnQpLA0KICAgICAgICAgICAgIHRlY2hfc2UgPSB0ZWNoX3NkL3NxcnQodGVjaF9OKSkNCnN0ZDMNCmBgYA0KIyMjU3VtbWFyaXplIGJ5IGluamVjdGlvbg0KYGBge3J9DQpzdGQ0IDwtIHN0ZDMgJT4lIA0KICBncm91cF9ieShOYW5vX2RheSxXaGVuLHBhcnRpY2xlX3NpemUpICU+JSANCiAgc3VtbWFyaXNlKCBpbmpfTiA9IGxlbmd0aCh0ZWNoX21lYW4pLA0KICAgICAgICAgICAgIGlual9tZWFuID0gbWVhbih0ZWNoX21lYW4pLA0KICAgICAgICAgICAgIGlual9zZCA9IHNkKHRlY2hfbWVhbiksDQogICAgICAgICAgICAgaW5qX3NlID0gaW5qX3NkL3NxcnQoaW5qX04pKQ0Kc3RkNA0KYGBgDQoNCg0KIyMjUGxvdCBiZWZvcmUgYW5kIGFmdGVyIHBsb3RzLCBmYWNldCBieSBleHBlcmltZW50YWwgZGF5DQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnN0ZF9kYXkgPC0gc3RkNCAlPiUgDQogIGdncGxvdChhZXMoeD1wYXJ0aWNsZV9zaXplLHk9aW5qX21lYW4sY29sb3I9V2hlbikpKw0KICBnZW9tX3JpYmJvbihhZXMoeW1pbj1pbmpfbWVhbi1pbmpfc2UsIHltYXg9aW5qX21lYW4raW5qX3NlKSxhbHBoYT0wLjIsZmlsbCA9IGFscGhhKCdncmV5MTInLCAwLjIpKSArICNlcnJvciBiYXJzDQogIGdlb21fbGluZShzaXplPTIpICsgeGxpbSgwLDUwMCkrICNsaW5lIHNpemUsIHgtYXhpcyBzY2FsZQ0KICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kPWMoMCwwKSkrICNzZXQgYm90dG9tIG9mIGdyYXBoDQogIHhsYWIoIlBhcnRpY2xlIFNpemUiKSArICMgWCBheGlzIGxhYmVsDQogIHlsYWIoIlxuTWVhbiBQYXJ0aWNsZSBDb25jZW50cmF0aW9uXG4oUGFydGljbGVzL21sKVxuIikgKyAjIFkgYXhpcyBsYWJlbA0KICBnZ3RpdGxlKCJOYW5vc2lnaHQgSGlzdG9ncmFtIG9mXG4xMDBubSBzdGFuZGFyZHMiKSsgI3RpdGxlDQogIGxhYnMoY29sb3I9IldoZW4iKSsgI0xhYmVsIHRhYmxlIHRpdGxlDQogIGZhY2V0X2dyaWQoLiB+IE5hbm9fZGF5KQ0Kc3RkX2RheQ0KDQpgYGANCiMjI1Bsb3QgZmFjZXQgYnkgd2hlbiBhbmQgZXhwZXJpbWVudGFsIGRheQ0KYGBge3J9DQpzdGRfZGF5X2ZhY2V0IDwtIHN0ZDQgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9cGFydGljbGVfc2l6ZSx5PWlual9tZWFuLGNvbG9yPVdoZW4pKSsNCiAgZ2VvbV9yaWJib24oYWVzKHltaW49aW5qX21lYW4taW5qX3NlLCB5bWF4PWlual9tZWFuK2lual9zZSksYWxwaGE9MC4yLGZpbGwgPSBhbHBoYSgnZ3JleTEyJywgMC4yKSkgKyAjZXJyb3IgYmFycw0KICBnZW9tX2xpbmUoc2l6ZT0yKSArIHhsaW0oMCw1MDApKyAjbGluZSBzaXplLCB4LWF4aXMgc2NhbGUNCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZD1jKDAsMCkpKyAjc2V0IGJvdHRvbSBvZiBncmFwaA0KICB4bGFiKCJQYXJ0aWNsZSBTaXplIikgKyAjIFggYXhpcyBsYWJlbA0KICB5bGFiKCJcbk1lYW4gUGFydGljbGUgQ29uY2VudHJhdGlvblxuKFBhcnRpY2xlcy9tbClcbiIpICsgIyBZIGF4aXMgbGFiZWwNCiAgZ2d0aXRsZSgiTmFub3NpZ2h0IEhpc3RvZ3JhbSBvZlxuMTAwbm0gc3RhbmRhcmRzIikrICN0aXRsZQ0KICBsYWJzKGNvbG9yPSJDb25kaXRpb24iKSsgI0xhYmVsIHRhYmxlIHRpdGxlDQogIGZhY2V0X2dyaWQoV2hlbiB+IE5hbm9fZGF5KQ0Kc3RkX2RheV9mYWNldA0KDQpnZ3NhdmUocGxvdCA9IHN0ZF9kYXlfZmFjZXQsICJTdGFuZGFyZHNfaGlzdG9ncmFtLnBuZyIsIA0KICAgICAgIGhlaWdodCA9IDUsIHdpZHRoID0gNywgZHBpID0gNjAwLCB1bml0cz0gImluIikNCg0KYGBgDQoNCiMjI1BhcnRpY2xlIGNvbmNlbnRyYXRpb25zIGZyb20gZWFjaCBleHBlcmltZW50YWwgZGF5DQpgYGB7cn0NCnN0ZF9kZiA8LSBzdGQ0ICU+JSANCiAgZ3JvdXBfYnkoTmFub19kYXksV2hlbikgJT4lIA0KICBzdW1tYXJpc2UodG90YWw9c3VtKGlual9tZWFuKSkNCnN0ZF9kZg0KYGBgDQojIyNCYXIgZ3JhcGggb2YgcGFydGljbGUgY29uY2VudHJhdGlvbnMNCmBgYHtyfQ0Kc3RkX2Jhcl9wbG90IDwtIHN0ZF9kZiAlPiUgDQogIGdncGxvdChhZXMoeD1OYW5vX2RheSx5PXRvdGFsLGZpbGw9V2hlbikpKw0KICBnZW9tX2NvbChwb3NpdGlvbj0iZG9kZ2UiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZD1jKDAsMCkpKyAjc2V0IGJvdHRvbSBvZiBncmFwaA0KICB4bGFiKCJFeHBlcmltZW50YWwgRGF5IikgKyAjIFggYXhpcyBsYWJlbA0KICB5bGFiKCJcbk1lYW4gQ29uY2VudHJhdGlvblxuKFBhcnRpY2xlcy9tbClcbiIpICsgIyBZIGF4aXMgbGFiZWwNCiAgZ2d0aXRsZSgiTmFub3NpZ2h0IEhpc3RvZ3JhbSBvZlxuMTAwbm0gc3RhbmRhcmRzIikrICN0aXRsZQ0KICBsYWJzKGNvbG9yPSJXaGVuIikgI0xhYmVsIHRhYmxlIHRpdGxlDQoNCnN0ZF9iYXJfcGxvdA0KDQojIGdnc2F2ZShwbG90ID0gc3RkX2Jhcl9wbG90LCAic3RkX2Jhcl9wbG90LnBuZyIsDQojICAgICAgICBoZWlnaHQgPSA1LCB3aWR0aCA9IDcsIGRwaSA9IDMwMCwgdW5pdHM9ICJpbiIpDQpgYGANCiMjI0ludHJhYXNzYXkgdmFyaWFiaWxpdHkNCmBgYHtyfQ0KSW50cmEuYXNzYXlfY3YgPC0gc3RkX2RmICU+JSANCiAgZ3JvdXBfYnkoTmFub19kYXkpICU+JSANCiAgc3VtbWFyaXNlKERheV9OID0gbGVuZ3RoKHRvdGFsKSwNCiAgICAgICAgICAgICBEYXlfbWVhbiA9IG1lYW4odG90YWwpLA0KICAgICAgICAgICAgIERheV9zZCA9IHNkKHRvdGFsKSwNCiAgICAgICAgICAgICBEYXlfc2UgPSBEYXlfc2Qvc3FydChEYXlfTiksDQogICAgICAgICAgICBEYXlfY3YgPSBEYXlfc2QvRGF5X21lYW4gKQ0KSW50cmEuYXNzYXlfY3YNCg0KIyB3cml0ZV9jc3YoSW50cmEuYXNzYXlfY3YsICJJbnRyYS5hc3NheV9jdi5jc3YiKQ0KYGBgDQoNCiMjI0ludGVyIGFzc2F5IHZhcmlhYmlsaXR5DQpgYGB7cn0NCkludGVyLmFzc2F5IDwtIEludHJhLmFzc2F5X2N2ICU+JSANCiBzdW1tYXJpc2UoRXhwX04gPSBsZW5ndGgoRGF5X21lYW4pLA0KICAgICAgICAgICAgIEV4cF9tZWFuID0gbWVhbihEYXlfbWVhbiksDQogICAgICAgICAgICAgRXhwX3NkID0gc2QoRGF5X21lYW4pLA0KICAgICAgICAgICAgIEV4cF9zZSA9IEV4cF9zZC9zcXJ0KEV4cF9OKSwNCiAgICAgICAgICAgIEV4cF9jdiA9IEV4cF9zZC9FeHBfbWVhbiApDQpJbnRlci5hc3NheQ0KDQojIHdyaXRlX2NzdihJbnRlci5hc3NheSwgIkludGVyLmFzc2F5LmNzdiIpDQpgYGANCg0KIyNGYWN0b3IgdGhlIGRhdGEgaW50byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMNCg0KYGBge3J9DQojIFJlZmFjdG9yaW5nIENvbHVtbnMgZm9yIHNhbXBsZXMNCmRhdGEyJFNhbXBsZV9JRCA8LSBhcy5mYWN0b3IoZGF0YTIkU2FtcGxlX0lEKQ0KZGF0YTIkRGlsdXRpb25fZmFjdG9yIDwtIGFzLm51bWVyaWMoZGF0YTIkRGlsdXRpb25fZmFjdG9yKQ0KZGF0YTIkSW5qZWN0aW9uPC0gYXMuZmFjdG9yKGRhdGEyJEluamVjdGlvbikNCmRhdGEyJFRlY2hfcmVwIDwtIGFzLm51bWVyaWMoZGF0YTIkVGVjaF9yZXApDQoNCg0KIyBSZWZhY3RvcmluZyBDT2x1bW5zIGZvciB0aW1lY291cnNlDQprZXkkU2FtcGxlX0lEIDwtIGFzLmZhY3RvcihrZXkkU2FtcGxlX0lEKQ0Ka2V5JFByb2ZpbGUgPC0gYXMuZmFjdG9yKGtleSRQcm9maWxlKQ0Ka2V5JFNleCA8LSBhcy5mYWN0b3Ioa2V5JFNleCkNCmtleSRBZ2UgPC0gYXMubnVtZXJpYyhrZXkkQWdlKQ0KYGBgDQoNCiMjQmFjayBjYWxjdWxhdGUgdGhlIG9yaWdpbmFsIGNvbmNlbnRyYXRpb24gb2YgdGhlIHNhbXBsZQ0KYGBge3J9DQpkYXRhMiA8LSBkYXRhMiAlPiUgDQogIG11dGF0ZShUcnVlX0NvdW50PURpbHV0aW9uX2ZhY3RvcipDb3VudCkNCmRhdGEyDQpgYGANCg0KIyMgQXZlcmFnZSB0aGUgdGhyZWUgdGVjaG5pY2FsIHJlcGxpY2F0ZSByZWFkaW5ncw0KYGBge3IsIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1GQUxTRX0NCmRhdGEzIDwtIGRhdGEyICU+JSANCiAgZ3JvdXBfYnkocGFydGljbGVfc2l6ZSxTYW1wbGVfSUQsRGlsdXRpb25fZmFjdG9yLEluamVjdGlvbikgJT4lIA0KICBzdW1tYXJpc2UoIHRlY2hfTiA9IGxlbmd0aChUcnVlX0NvdW50KSwNCiAgICAgICAgICAgICB0ZWNoX21lYW4gPSBtZWFuKFRydWVfQ291bnQpLA0KICAgICAgICAgICAgIHRlY2hfc2QgPSBzZChUcnVlX0NvdW50KSwNCiAgICAgICAgICAgICB0ZWNoX3NlID0gdGVjaF9zZC9zcXJ0KHRlY2hfTikpDQpkYXRhMw0KDQoNCnRlc3QxIDwtIGxlZnRfam9pbihrZXksZGF0YTMsIGJ5PSAiU2FtcGxlX0lEIikNCmBgYA0KDQoNCiMjU3VtbWFyaXplIHNhbXBsZXMgYnkgaW5qZWN0aW9uIChhdmVyYWdlIGJvdGggaW5qZWN0aW9ucykNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KDQpkYXRhNCA8LSBkYXRhMyAlPiUgDQogIGdyb3VwX2J5KHBhcnRpY2xlX3NpemUsU2FtcGxlX0lELERpbHV0aW9uX2ZhY3RvcikgJT4lIA0KICBzdW1tYXJpc2UoIGlual9OID0gbGVuZ3RoKHRlY2hfbWVhbiksDQogICAgICAgICAgICAgaW5qX21lYW4gPSBtZWFuKHRlY2hfbWVhbiksDQogICAgICAgICAgICAgaW5qX3NkID0gc2QodGVjaF9tZWFuKSwNCiAgICAgICAgICAgICBpbmpfc2UgPSBpbmpfc2Qvc3FydChpbmpfTikpDQpkYXRhNA0KDQp0ZXN0MiA8LSBsZWZ0X2pvaW4oa2V5LGRhdGE0LCBieT0gIlNhbXBsZV9JRCIpDQoNCnRlc3QyDQpgYGANCg0KI1F1aWNrIHZpc3VhbGl6YXRpb25zDQoNCiMjIyBHcmFwaGluZyBhbGwgc2FtcGxlcw0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQp0ZXN0MSRTYW1wbGVfSURfY29ycmVjdCA9IGZhY3Rvcih0ZXN0MSRTYW1wbGVfSUQsIGxldmVscz1jKCcxJywnMicsJzMnLCc0JywnNScsJzYnKSkNCnRlc3QxJFByb2ZpbGUgPSBmYWN0b3IodGVzdDEkUHJvZmlsZSwgbGV2ZWxzPWMoIk5vcm1hbCIsICJUZ0FBIiwgIkh5cG90aHlyb2lkIikpDQoNCmdyYXBoMSA8LSB0ZXN0MSAlPiUNCiAgZ2dwbG90KGFlcyh4PXBhcnRpY2xlX3NpemUsIHk9dGVjaF9tZWFuLGNvbG9yPUluamVjdGlvbiApKSsgI3Bsb3QNCiAgZ2VvbV9yaWJib24oYWVzKHltaW49dGVjaF9tZWFuLXRlY2hfc2UsDQogICAgICAgICAgICAgICAgICB5bWF4PXRlY2hfbWVhbit0ZWNoX3NlKSwNCiAgICAgICAgICAgICAgICAgIGFscGhhPTAuMixmaWxsID0gYWxwaGEoJ2dyZXkxMicsIDAuMikpICsgI2Vycm9yIGJhcnMNCiAgZ2VvbV9saW5lKHNpemU9Mi4wKSArIHhsaW0oMCw1MDApKyAjbGluZSBzaXplLCB4LWF4aXMgc2NhbGUNCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZD1jKDAsMCkpKyAjc2V0IGJvdHRvbSBvZiBncmFwaA0KICB4bGFiKCJQYXJ0aWNsZSBTaXplIikgKyAjIFggYXhpcyBsYWJlbA0KICB5bGFiKCJcbk1lYW4gUGFydGljbGUgQ29uY2VudHJhdGlvblxuKFBhcnRpY2xlcy9tbClcbiIpICsgIyBZIGF4aXMgbGFiZWwNCiAgZ2d0aXRsZSgiTmFub3NpZ2h0IEhpc3RvZ3JhbSBvZlxuTW91c2UgUGxhc21hIFRocm91Z2hvdXQgUHJlZ25hbmN5IikrICN0aXRsZQ0KICBsYWJzKGNvbG9yPSJJbmplY3Rpb24iKSsgI0xhYmVsIHRhYmxlIHRpdGxlDQogIGZhY2V0X3dyYXAoIH4gU2FtcGxlX0lEX2NvcnJlY3QsIG5jb2w9NikNCg0KZ3JhcGgxDQoNCg0KIyBnZ3NhdmUocGxvdCA9IGdyYXBoMSwgIk5hbm9zaWdodF9zYW1wbGVfaGlzdG9ncmFtX3Bsb3QucG5nIiwNCiMgICAgICAgIGhlaWdodCA9IDEwLCB3aWR0aCA9IDE0LCBkcGkgPSA0MDAsIHVuaXRzPSAiaW4iKQ0KDQpgYGANCg0KIyMjI0xvb2tpbmcgYXQgaW5kaXZpZHVhbCBnZXN0YXRpb25hbCBkYXkgbmFub3NpZ2h0IGxpbmUgcGxvdHMgIA0KDQoqKlNhbXBsZSAxKioNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Kc2FtcGxlMV9oaXN0b2dyYW0gPC0gdGVzdDEgJT4lDQogIGZpbHRlcihTYW1wbGVfSUQgPT0gJzEnKSAlPiUgDQogIGdncGxvdChhZXMoeD1wYXJ0aWNsZV9zaXplLCB5PXRlY2hfbWVhbixjb2xvcj1JbmplY3Rpb24gKSkrICNwbG90DQogIGdlb21fcmliYm9uKGFlcyh5bWluPXRlY2hfbWVhbi10ZWNoX3NlLA0KICAgICAgICAgICAgICAgICAgeW1heD10ZWNoX21lYW4rdGVjaF9zZSksDQogICAgICAgICAgICAgICAgICBhbHBoYT0wLjIsZmlsbCA9IGFscGhhKCdncmV5MTInLCAwLjIpKSArICNlcnJvciBiYXJzDQogIGdlb21fbGluZShzaXplPTEuMCkgKyB4bGltKDAsNTAwKSsgI2xpbmUgc2l6ZSwgeC1heGlzIHNjYWxlDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQ9YygwLDApKSsgI3NldCBib3R0b20gb2YgZ3JhcGgNCiAgeGxhYigiUGFydGljbGUgU2l6ZSIpICsgIyBYIGF4aXMgbGFiZWwNCiAgeWxhYigiXG5NZWFuIFBhcnRpY2xlIENvbmNlbnRyYXRpb25cbihQYXJ0aWNsZXMvbWwpXG4iKSArICMgWSBheGlzIGxhYmVsDQogIGdndGl0bGUoIk5hbm9zaWdodCBIaXN0b2dyYW0gb2ZcbiBUZ0FBKyBNYWxlIikrICN0aXRsZQ0KICBsYWJzKGNvbG9yPSJJbmplY3Rpb24iKSsgI0xhYmVsIHRhYmxlIHRpdGxlDQogIGZhY2V0X3dyYXAoIH4gU2FtcGxlX0lEX2NvcnJlY3QpKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxNDApKw0KICBhbm5vdGF0ZSgidGV4dCIsIHg9IDIzNSwgeSA9IDNFOSwgbGFiZWw9ICIxNDBubSIpDQoNCnNhbXBsZTFfaGlzdG9ncmFtDQoNCg0KIyBnZ3NhdmUocGxvdCA9IHZpcmdpbl9oaXN0b2dyYW0sICJ2aXJnaW5faGlzdG9ncmFtLnBuZyIsDQojICAgICAgICBoZWlnaHQgPSAxMCwgd2lkdGggPSAxNCwgZHBpID0gMzAwLCB1bml0cz0gImluIikNCg0KYGBgDQoNCioqU2FtcGxlIDIqKiAgDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnNhbXBsZTFfaGlzdG9ncmFtIDwtIHRlc3QxICU+JQ0KICBmaWx0ZXIoU2FtcGxlX0lEID09ICcyJykgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9cGFydGljbGVfc2l6ZSwgeT10ZWNoX21lYW4sY29sb3I9SW5qZWN0aW9uICkpKyAjcGxvdA0KICBnZW9tX3JpYmJvbihhZXMoeW1pbj10ZWNoX21lYW4tdGVjaF9zZSwNCiAgICAgICAgICAgICAgICAgIHltYXg9dGVjaF9tZWFuK3RlY2hfc2UpLA0KICAgICAgICAgICAgICAgICAgYWxwaGE9MC4yLGZpbGwgPSBhbHBoYSgnZ3JleTEyJywgMC4yKSkgKyAjZXJyb3IgYmFycw0KICBnZW9tX2xpbmUoc2l6ZT0xLjApICsgeGxpbSgwLDUwMCkrICNsaW5lIHNpemUsIHgtYXhpcyBzY2FsZQ0KICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kPWMoMCwwKSkrICNzZXQgYm90dG9tIG9mIGdyYXBoDQogIHhsYWIoIlBhcnRpY2xlIFNpemUiKSArICMgWCBheGlzIGxhYmVsDQogIHlsYWIoIlxuTWVhbiBQYXJ0aWNsZSBDb25jZW50cmF0aW9uXG4oUGFydGljbGVzL21sKVxuIikgKyAjIFkgYXhpcyBsYWJlbA0KICBnZ3RpdGxlKCJOYW5vc2lnaHQgSGlzdG9ncmFtIG9mXG5Ob3JtYWwgRmVtYWxlIFNlcnVtIikrICN0aXRsZQ0KICBsYWJzKGNvbG9yPSJJbmplY3Rpb24iKSsgI0xhYmVsIHRhYmxlIHRpdGxlDQogIGZhY2V0X3dyYXAoIH4gU2FtcGxlX0lEX2NvcnJlY3QpKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxNDApKw0KICBhbm5vdGF0ZSgidGV4dCIsIHg9IDIzNSwgeSA9IDNFOSwgbGFiZWw9ICIxNDBubSIpDQoNCnNhbXBsZTFfaGlzdG9ncmFtDQoNCiMgZ2dzYXZlKHBsb3QgPSBnZDUuNV9oaXN0b2dyYW0sICJnZDUuNV9oaXN0b2dyYW0ucG5nIiwNCiMgICAgICAgIGhlaWdodCA9IDEwLCB3aWR0aCA9IDE0LCBkcGkgPSAzMDAsIHVuaXRzPSAiaW4iKQ0KDQoNCmBgYA0KDQoNCioqU2FtcGxlIDMqKiAgDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnNhbXBsZTNfaGlzdG9ncmFtIDwtIHRlc3QxICU+JQ0KICBmaWx0ZXIoU2FtcGxlX0lEID09ICczJykgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9cGFydGljbGVfc2l6ZSwgeT10ZWNoX21lYW4sY29sb3I9SW5qZWN0aW9uICkpKyAjcGxvdA0KICBnZW9tX3JpYmJvbihhZXMoeW1pbj10ZWNoX21lYW4tdGVjaF9zZSwNCiAgICAgICAgICAgICAgICAgIHltYXg9dGVjaF9tZWFuK3RlY2hfc2UpLA0KICAgICAgICAgICAgICAgICAgYWxwaGE9MC4yLGZpbGwgPSBhbHBoYSgnZ3JleTEyJywgMC4yKSkgKyAjZXJyb3IgYmFycw0KICBnZW9tX2xpbmUoc2l6ZT0xLjApICsgeGxpbSgwLDUwMCkrICNsaW5lIHNpemUsIHgtYXhpcyBzY2FsZQ0KICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kPWMoMCwwKSkrICNzZXQgYm90dG9tIG9mIGdyYXBoDQogIHhsYWIoIlBhcnRpY2xlIFNpemUiKSArICMgWCBheGlzIGxhYmVsDQogIHlsYWIoIlxuTWVhbiBQYXJ0aWNsZSBDb25jZW50cmF0aW9uXG4oUGFydGljbGVzL21sKVxuIikgKyAjIFkgYXhpcyBsYWJlbA0KICBnZ3RpdGxlKCJOYW5vc2lnaHQgSGlzdG9ncmFtIG9mXG5IeXBvdGh5cm9pZCBNYWxlIFNlcnVtIikrICN0aXRsZQ0KICBsYWJzKGNvbG9yPSJJbmplY3Rpb24iKSsgI0xhYmVsIHRhYmxlIHRpdGxlDQogIGZhY2V0X3dyYXAoIH4gU2FtcGxlX0lEX2NvcnJlY3QpKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxNDApKw0KICBhbm5vdGF0ZSgidGV4dCIsIHg9IDIzNSwgeSA9IDRFOSwgbGFiZWw9ICIxNDBubSIpDQoNCnNhbXBsZTNfaGlzdG9ncmFtDQoNCiMgZ2dzYXZlKHBsb3QgPSBnZDEwLjVfaGlzdG9ncmFtLCAiZ2QxMC41X2hpc3RvZ3JhbS5wbmciLA0KIyAgICAgICAgaGVpZ2h0ID0gMTAsIHdpZHRoID0gMTQsIGRwaSA9IDMwMCwgdW5pdHM9ICJpbiIpDQpgYGANCg0KKipTYW1wbGUgNCoqICANCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Kc2FtcGxlNF9oaXN0b2dyYW0gPC0gdGVzdDEgJT4lDQogIGZpbHRlcihTYW1wbGVfSUQgPT0gJzQnKSAlPiUgDQogIGdncGxvdChhZXMoeD1wYXJ0aWNsZV9zaXplLCB5PXRlY2hfbWVhbixjb2xvcj1JbmplY3Rpb24gKSkrICNwbG90DQogIGdlb21fcmliYm9uKGFlcyh5bWluPXRlY2hfbWVhbi10ZWNoX3NlLA0KICAgICAgICAgICAgICAgICAgeW1heD10ZWNoX21lYW4rdGVjaF9zZSksDQogICAgICAgICAgICAgICAgICBhbHBoYT0wLjIsZmlsbCA9IGFscGhhKCdncmV5MTInLCAwLjIpKSArICNlcnJvciBiYXJzDQogIGdlb21fbGluZShzaXplPTEuMCkgKyB4bGltKDAsNTAwKSsgI2xpbmUgc2l6ZSwgeC1heGlzIHNjYWxlDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQ9YygwLDApKSsgI3NldCBib3R0b20gb2YgZ3JhcGgNCiAgeGxhYigiUGFydGljbGUgU2l6ZSIpICsgIyBYIGF4aXMgbGFiZWwNCiAgeWxhYigiXG5NZWFuIFBhcnRpY2xlIENvbmNlbnRyYXRpb25cbihQYXJ0aWNsZXMvbWwpXG4iKSArICMgWSBheGlzIGxhYmVsDQogIGdndGl0bGUoIk5hbm9zaWdodCBIaXN0b2dyYW0gb2ZcblRnQUErIEZlbWFsZSBTZXJ1bSIpKyAjdGl0bGUNCiAgbGFicyhjb2xvcj0iSW5qZWN0aW9uIikrICNMYWJlbCB0YWJsZSB0aXRsZQ0KICBmYWNldF93cmFwKCB+IFNhbXBsZV9JRF9jb3JyZWN0KSsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMTQwKSsNCiAgYW5ub3RhdGUoInRleHQiLCB4PSAyMzUsIHkgPSAzRTksIGxhYmVsPSAiMTQwbm0iKQ0KDQoNCnNhbXBsZTRfaGlzdG9ncmFtDQoNCiMgZ2dzYXZlKHBsb3QgPSBnZDE0LjVfaGlzdG9ncmFtLCAiZ2QxNC41X2hpc3RvZ3JhbS5wbmciLA0KIyAgICAgICAgaGVpZ2h0ID0gMTAsIHdpZHRoID0gMTQsIGRwaSA9IDMwMCwgdW5pdHM9ICJpbiIpDQoNCmBgYA0KDQoNCg0KKipTYW1wbGUgNSoqICANCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Kc2FtcGxlNV9oaXN0b2dyYW0gPC0gdGVzdDEgJT4lDQogIGZpbHRlcihTYW1wbGVfSUQgPT0gJzUnKSAlPiUgDQogIGdncGxvdChhZXMoeD1wYXJ0aWNsZV9zaXplLCB5PXRlY2hfbWVhbixjb2xvcj1JbmplY3Rpb24gKSkrICNwbG90DQogIGdlb21fcmliYm9uKGFlcyh5bWluPXRlY2hfbWVhbi10ZWNoX3NlLA0KICAgICAgICAgICAgICAgICAgeW1heD10ZWNoX21lYW4rdGVjaF9zZSksDQogICAgICAgICAgICAgICAgICBhbHBoYT0wLjIsZmlsbCA9IGFscGhhKCdncmV5MTInLCAwLjIpKSArICNlcnJvciBiYXJzDQogIGdlb21fbGluZShzaXplPTEuMCkgKyB4bGltKDAsNTAwKSsgI2xpbmUgc2l6ZSwgeC1heGlzIHNjYWxlDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQ9YygwLDApKSsgI3NldCBib3R0b20gb2YgZ3JhcGgNCiAgeGxhYigiUGFydGljbGUgU2l6ZSIpICsgIyBYIGF4aXMgbGFiZWwNCiAgeWxhYigiXG5NZWFuIFBhcnRpY2xlIENvbmNlbnRyYXRpb25cbihQYXJ0aWNsZXMvbWwpXG4iKSArICMgWSBheGlzIGxhYmVsDQogIGdndGl0bGUoIk5hbm9zaWdodCBIaXN0b2dyYW0gb2Zcbk5vcm1hbCBNYWxlIFNlcnVtIikrICN0aXRsZQ0KICBsYWJzKGNvbG9yPSJJbmplY3Rpb24iKSsgI0xhYmVsIHRhYmxlIHRpdGxlDQogIGZhY2V0X3dyYXAoIH4gU2FtcGxlX0lEX2NvcnJlY3QpKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxNDApKw0KICBhbm5vdGF0ZSgidGV4dCIsIHg9IDIzNSwgeSA9IDNFOSwgbGFiZWw9ICIxNDBubSIpDQoNCg0Kc2FtcGxlNV9oaXN0b2dyYW0NCg0KIyBnZ3NhdmUocGxvdCA9IGdkMTcuNV9oaXN0b2dyYW0sICJnZDE3LjVfaGlzdG9ncmFtLnBuZyIsDQojICAgICAgICBoZWlnaHQgPSAxMCwgd2lkdGggPSAxNCwgZHBpID0gMzAwLCB1bml0cz0gImluIikNCg0KDQpgYGANCg0KDQoqKlNhbXBsZSA2KiogIA0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpzYW1wbGU2X2hpc3RvZ3JhbSA8LSB0ZXN0MSAlPiUNCiAgZmlsdGVyKFNhbXBsZV9JRCA9PSAnNicpICU+JSANCiAgZ2dwbG90KGFlcyh4PXBhcnRpY2xlX3NpemUsIHk9dGVjaF9tZWFuLGNvbG9yPUluamVjdGlvbiApKSsgI3Bsb3QNCiAgZ2VvbV9yaWJib24oYWVzKHltaW49dGVjaF9tZWFuLXRlY2hfc2UsDQogICAgICAgICAgICAgICAgICB5bWF4PXRlY2hfbWVhbit0ZWNoX3NlKSwNCiAgICAgICAgICAgICAgICAgIGFscGhhPTAuMixmaWxsID0gYWxwaGEoJ2dyZXkxMicsIDAuMikpICsgI2Vycm9yIGJhcnMNCiAgZ2VvbV9saW5lKHNpemU9MS4wKSArIHhsaW0oMCw1MDApKyAjbGluZSBzaXplLCB4LWF4aXMgc2NhbGUNCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZD1jKDAsMCkpKyAjc2V0IGJvdHRvbSBvZiBncmFwaA0KICB4bGFiKCJQYXJ0aWNsZSBTaXplIikgKyAjIFggYXhpcyBsYWJlbA0KICB5bGFiKCJcbk1lYW4gUGFydGljbGUgQ29uY2VudHJhdGlvblxuKFBhcnRpY2xlcy9tbClcbiIpICsgIyBZIGF4aXMgbGFiZWwNCiAgZ2d0aXRsZSgiTmFub3NpZ2h0IEhpc3RvZ3JhbSBvZlxuSHlwb3RoeXJvaWQgTWFsZSBTZXJ1bSIpKyAjdGl0bGUNCiAgbGFicyhjb2xvcj0iSW5qZWN0aW9uIikrICNMYWJlbCB0YWJsZSB0aXRsZQ0KICBmYWNldF93cmFwKCB+IFNhbXBsZV9JRF9jb3JyZWN0KSsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMTQwKSsNCiAgYW5ub3RhdGUoInRleHQiLCB4PSAyMzUsIHkgPSA0RTEwLCBsYWJlbD0gIjE0MG5tIikNCg0KDQpzYW1wbGU2X2hpc3RvZ3JhbQ0KDQojIGdnc2F2ZShwbG90ID0gb25lLmRheS5wb3N0LnBhcnR1bV9oaXN0b2dyYW0sICJvbmUuZGF5LnBvc3QucGFydHVtX2hpc3RvZ3JhbS5wbmciLA0KIyAgICAgICAgaGVpZ2h0ID0gMTAsIHdpZHRoID0gMTQsIGRwaSA9IDMwMCwgdW5pdHM9ICJpbiIpDQoNCg0KDQpgYGANCg0KIyMjIFBhcnRpY2xlIGNvbmNlbnRyYXRpb24gdmFsdWVzIGZvciBlYWNoIG9mIHRoZSAzNiBzYW1wbGVzDQpgYGB7cn0NCnRlc3QzIDwtIHRlc3QyICU+JSANCiAgZ3JvdXBfYnkoUHJvZmlsZSxTYW1wbGVfSUQpICU+JSANCiAgc3VtbWFyaXNlKHBhcnRpY2xlX2NvbmM9c3VtKGlual9tZWFuKSkNCnRlc3QzDQoNCiMgd3JpdGVfY3N2KHRlc3QzLCAiU2FtcGxlX21lYW5zLmNzdiIpDQpgYGANCiMjI0JveHBsb3Qgb2YgYWxsIHZhbHVlcw0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQp0ZXN0MyRQcm9maWxlIDwtIGZhY3Rvcih0ZXN0MyRQcm9maWxlLCBsZXZlbHMgPSBjKCJOb3JtYWwiLCJUZ0FBIiwgIkh5cG90aHlyb2lkIikpDQoNCnBsb3QxIDwtIHRlc3QzICU+JSANCiAgZ3JvdXBfYnkoUHJvZmlsZSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9IFByb2ZpbGUsIHkgPSBwYXJ0aWNsZV9jb25jLzFFOSwgY29sb3I9UHJvZmlsZSkpICsNCiAgZ2VvbV9ib3hwbG90KGNvbG91cj0iYmxhY2siLGZpbGw9TkEpICsgDQogIGdlb21fcG9pbnQoYWVzKHRleHQgPSBwYXN0ZSgiU2FtcGxlIElEOiIsIFNhbXBsZV9JRCkpLA0KICAgICAgICAgICAgIHBvc2l0aW9uPSdqaXR0ZXInLHNpemU9MykrDQogIHhsYWIoIlxuRGlzZWFzZSBTdGF0ZVxuIikgKyAjIFggYXhpcyBsYWJlbA0KICB5bGFiKCJcbjEwXjkgRXhvc29tZXMvbWxcbiIpICsgIyBZIGF4aXMgbGFiZWwNCiAgZ2d0aXRsZSgiU2VydW0gRXhvc29tZSBDb25jZW50cmF0aW9uXG5vZiBDYW5pbmUgRGlzZWFzZSBTdGF0ZXMgKEFsbCBTYW1wbGVzKVxuIikrICN0aXRsZQ0KICBsYWJzKGNvbG9yPSJQcm9maWxlIikrICMgTGFiZWwgdGFibGUgdGl0bGUNCiAgc2NhbGVfeF9kaXNjcmV0ZSggIyBDaGFuZ2UgWCBheGlzIGxhYmVsDQogICAgICAgICAgICAgICAgICBsYWJlbHM9YygiTm9ybWFsIiwiVGdBQSsiLCAiSHlwb3RoeXJvaWQiKSkgKw0KICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShsYWJlbHM9YygiTm9ybWFsIiwiVGdBQSsiLCAiSHlwb3RoeXJvaWQiKSkgIyBDaGFuZ2UgTGVnZW5kDQoNCnBsb3QxDQoNCiMgZ2dzYXZlKHBsb3QgPSBwbG90MSwgIkV4b3NvbWVfYm94cGxvdF9wbG90X2FsbC5wbmciLCBoZWlnaHQgPSA1LCB3aWR0aCA9IDcsIHVuaXRzID0gImluIiwgZHBpID0gNjAwKQ0KDQoNCmBgYA0KDQojI1Bsb3RseSBvZiBhbGwgdmFsdWVzDQpgYGB7cn0NCiAgZ2dwbG90bHkocGxvdDEpDQpgYGANCg0KIyMjQm94IHBsb3Qgd2l0aG91dCBzYW1wbGUgNg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCnBsb3QxX25vX3NhbXBsZV82IDwtIHRlc3QzICU+JSANCiAgZmlsdGVyKCFTYW1wbGVfSUQgPT0gJzYnKSAlPiUgDQogIGdyb3VwX2J5KFByb2ZpbGUpICU+JSANCiAgZ2dwbG90KGFlcyh4PSBQcm9maWxlLCB5ID0gcGFydGljbGVfY29uYy8xRTksIGNvbG9yPVByb2ZpbGUpKSArDQogIGdlb21fYm94cGxvdChjb2xvdXI9ImJsYWNrIixmaWxsPU5BKSArIA0KICBnZW9tX3BvaW50KGFlcyh0ZXh0ID0gcGFzdGUoIlNhbXBsZSBJRDoiLCBTYW1wbGVfSUQpKSwNCiAgICAgICAgICAgICBwb3NpdGlvbj0naml0dGVyJyxzaXplPTMpKw0KICB4bGFiKCJcbkRpc2Vhc2UgU3RhdGVcbiIpICsgIyBYIGF4aXMgbGFiZWwNCiAgeWxhYigiXG4xMF45IEV4b3NvbWVzL21sXG4iKSArICMgWSBheGlzIGxhYmVsDQogIGdndGl0bGUoIlNlcnVtIEV4b3NvbWUgQ29uY2VudHJhdGlvblxub2YgQ2FuaW5lIERpc2Vhc2UgU3RhdGVzIChXaXRob3V0IHNhbXBsZSA2KVxuIikrICN0aXRsZQ0KICBsYWJzKGNvbG9yPSJQcm9maWxlIikrICMgTGFiZWwgdGFibGUgdGl0bGUNCiAgc2NhbGVfeF9kaXNjcmV0ZSggIyBDaGFuZ2UgWCBheGlzIGxhYmVsDQogICAgICAgICAgICAgICAgICBsYWJlbHM9YygiTm9ybWFsIiwiVGdBQSsiLCAiSHlwb3RoeXJvaWQiKSkgKw0KICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShsYWJlbHM9YygiTm9ybWFsIiwiVGdBQSsiLCAiSHlwb3RoeXJvaWQiKSkgIyBDaGFuZ2UgTGVnZW5kDQoNCnBsb3QxX25vX3NhbXBsZV82DQoNCiMgZ2dzYXZlKHBsb3QgPSBwbG90MV9ub19zYW1wbGVfNiwgIkV4b3NvbWVfYm94cGxvdF9wbG90X25vNi5wbmciLCBoZWlnaHQgPSA1LCB3aWR0aCA9IDcsIHVuaXRzID0gImluIiwgZHBpID0gNjAwKQ0KDQpgYGANCg0KIyNQbG90bHkgd2l0aG91dCBzYW1wbGUgNg0KYGBge3J9DQogIGdncGxvdGx5KHBsb3QxX25vX3NhbXBsZV82KQ0KYGBgDQoNCg0KDQoNCiMjIyBTdW1tYXJ5IHN0YXRpc3RpY3Mgb2YgcGFydGljbGUgY29uY2VudHJhdGlvbiAoYXZlcmFnaW5nIGZvciBlYWNoIHRpbWUgcG9pbnQpDQpgYGB7cn0NCnRlc3Q0IDwtIHRlc3QzICU+JSANCiAgZ3JvdXBfYnkoUHJvZmlsZSkgJT4lIA0KICBzdW1tYXJpc2UoUHJvZmlsZV9OPWxlbmd0aChwYXJ0aWNsZV9jb25jKSwNCiAgICAgICAgICAgIFByb2ZpbGVfbWVhbiA9IG1lYW4ocGFydGljbGVfY29uYyksDQogICAgICAgICAgICBQcm9maWxlX3NkID0gc2QocGFydGljbGVfY29uYyksDQogICAgICAgICAgICBQcm9maWxlX3NlID0gUHJvZmlsZV9zZC9zcXJ0KFByb2ZpbGVfTikpDQp0ZXN0NA0KDQojIHdyaXRlX2Nzdih0ZXN0NCwiU3VtbWFyeV9zdGF0aXN0aWNzX2Zvcl9lYWNoX3Byb2ZpbGUuY3N2IikNCmBgYA0KDQoNCg0KDQoNCg0KDQojIyNCYXIgcGxvdA0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQpwbG90IDwtIHRlc3Q0ICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gUHJvZmlsZSwgeSA9IFByb2ZpbGVfbWVhbi8xRTksIGZpbGwgPSBQcm9maWxlKSkrICNwbG90DQogIGdlb21fY29sKCkrDQogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBQcm9maWxlX21lYW4vMWU5LVByb2ZpbGVfc2UvMWU5LA0KICAgICAgICAgICAgICAgICAgICB5bWF4ID0gUHJvZmlsZV9tZWFuLzFlOStQcm9maWxlX3NlLzFlOSksIHdpZHRoPS40LA0KICAgICAgICAgICAgICAgIHNpemUgPSAwLjgsIGNvbG91ciA9ICJibGFjayIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoLjkpKSArICNlcnJvciBiYXJzDQogIHhsYWIoIlxuRGlzZWFzZSBTdGF0ZVxuIikgKyAjIFggYXhpcyBsYWJlbA0KICB5bGFiKCJcbk1lYW4gQ29uY2VudHJhdGlvblxuKDEwXjkgVmVzaWNsZXMvbWwpXG4iKSArICMgWSBheGlzIGxhYmVsDQogIGdndGl0bGUoIlNlcnVtIEV4b3NvbWUgQ29uY2VudHJhdGlvblxub2YgQ2FuaW5lIERpc2Vhc2UgU3RhdGVzKEFsbCBTYW1wbGVzKVxuIikrICN0aXRsZQ0KICBndWlkZXMoZmlsbD1GQUxTRSkgKyAjIFJlbW92ZSBsZWdlbmQNCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZD1jKDAsMCkpKyAjc2V0IGJvdHRvbSBvZiBncmFwaA0KICBzY2FsZV94X2Rpc2NyZXRlKCAjIENoYW5nZSBYIGF4aXMgbGFiZWwNCiAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJOb3JtYWwiLCJUZ0FBKyIsICJIeXBvdGh5cm9pZCIpKSArDQogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKGxhYmVscz1jKCJOb3JtYWwiLCJUZ0FBKyIsICJIeXBvdGh5cm9pZCIpKSAjIENoYW5nZSBMZWdlbmQNCg0KDQpwbG90DQoNCg0KZ2dzYXZlKCJWZXNpY2xlX2JhcnBsb3QucG5nIiwgaGVpZ2h0ID0gNSwgd2lkdGggPSA3LCB1bml0cyA9ICJpbiIsIGRwaSA9IDYwMCkNCmBgYA0KDQojU3RhdGlzdGljcyBvbiBBTEwgc2l6ZXMNCg0KDQojIyNTaGFwaXJvIHRlc3QNCmBgYHtyfQ0KdGlkeShzaGFwaXJvLnRlc3QodGVzdDMkcGFydGljbGVfY29uYykpDQoNCmBgYA0KDQo=